package com.rs.game.player.content;

	import java.util.concurrent.CopyOnWriteArrayList;

	import com.rs.cache.loaders.ItemDefinitions;
import com.rs.game.item.Item;
import com.rs.game.player.Player;
import com.rs.utils.ItemExamines;
import com.rs.utils.ItemSetsKeyGenerator;
import com.rs.utils.ShopsHandler;

	public class Shop {
		
		private static final int MAIN_STOCK_ITEMS_KEY = ItemSetsKeyGenerator.generateKey();

		private static final int MAX_SHOP_ITEMS = 40;
		public static final int COINS = 995;

		private String name;
		private Item[] mainStock;
		private int[] defaultQuantity;
		private Item[] generalStock;
		private int money;
		private int amount;
		
		public static int[][] loyaltyPrices = { { 22298, 5000 }, { 23862, 5000 },
			{ 22925, 5000 }, { 23852, 5000 }, { 22909, 5000 },{ 22903, 5000 }, 
			{ 20068, 3500 }, { 6729, 150 }, { 15332, 50 }, 
			{ 10548, 3750 }, { 10551, 4250 },{ 12512, 2500 }, { 12514, 2500 }, 
			{ 12516, 2500 }, { 12518, 2500 },{ 12520, 2500 }, { 12522, 2500 }, 
			{12469, 5000}, {12471, 5000}, {12473, 5000}, {12475, 5000}, {4151, 3500} };
		
		public static int[][] Voteprices = { {17295, 80}, {10887, 45}, {11663, 25}, {11664, 25}, {11665, 25}, {8840, 30}, {8839, 25}, {8842, 15}, {19712, 20},
		{15834, 25}, {15835, 75}, // armour and weapons
		{1037, 15}, {6666, 5}, {18706, 50}, {18707, 40}, {18708, 20}, {18709, 30}, {21580, 15}, {23674, 40}, {18667, 50}, {18743, 25}, {18744, 20},
		{18745, 20}, {18746, 20} }; //cosmetic

		
		private CopyOnWriteArrayList<Player> viewingPlayers;

		public Shop(String name, int money, Item[] mainStock, boolean isGeneralStore) {
			viewingPlayers = new CopyOnWriteArrayList<Player>();
			this.name = name;
			this.money = money;
			this.mainStock = mainStock;
			defaultQuantity = new int[mainStock.length];
			for (int i = 0; i < defaultQuantity.length; i++) 
				defaultQuantity[i] = mainStock[i].getAmount();
			if (isGeneralStore && mainStock.length < MAX_SHOP_ITEMS)
				generalStock = new Item[MAX_SHOP_ITEMS - mainStock.length];
		}

		public boolean isGeneralStore() {
			return generalStock != null;
		}

		public void addPlayer(final Player player) {
			viewingPlayers.add(player);
			player.getTemporaryAttributes().put("Shop", this);
			player.refreshMoneyPouch();
			player.setCloseInterfacesEvent(new Runnable() {
				@Override
				public void run() {
					viewingPlayers.remove(player);
					player.getTemporaryAttributes().remove("Shop");
					player.getTemporaryAttributes().remove("shop_buying");
					player.getTemporaryAttributes().remove("amount_shop");
				}
			});
			player.getPackets().sendConfig(118, MAIN_STOCK_ITEMS_KEY);
			player.getPackets().sendConfig(1496, -1);
			player.getPackets().sendConfig(532, money);
			player.getPackets().sendConfig(2565, 0);
			sendStore(player);
			player.getPackets().sendGlobalConfig(199, -1);
			player.getInterfaceManager().sendInterface(1265);
			for (int i = 0; i < MAX_SHOP_ITEMS; i++)
				player.getPackets().sendGlobalConfig(946 + i, i < defaultQuantity.length ? defaultQuantity[i]: generalStock != null ? 0 : -1);// prices
			player.getPackets().sendGlobalConfig(1241, 16750848);
			player.getPackets().sendGlobalConfig(1242, 15439903);
			player.getPackets().sendGlobalConfig(741, -1);
			player.getPackets().sendGlobalConfig(743, -1);
			player.getPackets().sendGlobalConfig(744, 0);
			if (generalStock != null)
				player.getPackets().sendHideIComponent(1265, 19, false);
			player.getPackets().sendIComponentSettings(1265, 20, 0, getStoreSize() * 6, 1150);
			player.getPackets().sendIComponentSettings(1265, 26, 0, getStoreSize() * 6, 82903066);
			sendInventory(player);
			player.getPackets().sendIComponentText(1265, 85, name);
			player.getTemporaryAttributes().put("shop_buying", true);
			player.getTemporaryAttributes().put("amount_shop", 1);
		}

		public void sendInventory(Player player) {
			player.getInterfaceManager().sendInventoryInterface(1266);
			player.getPackets().sendItems(93, player.getInventory().getItems());
			player.getPackets().sendUnlockIComponentOptionSlots(1266, 0, 0, 27, 0,
					1, 2, 3, 4, 5);
			player.getPackets().sendInterSetItemsOptionsScript(1266, 0, 93, 4, 7,
					"Value", "Sell 1", "Sell 5", "Sell 10", "Sell 50", "Examine");
		}
		//cid 67
		public void buy(Player player, int clickSlot, int quantity) {
			if (clickSlot >= getStoreSize())
				return;
			Item item = clickSlot >= mainStock.length ? generalStock[clickSlot
					- mainStock.length] : mainStock[clickSlot];
			if (item == null)
				return;
			if (item.getAmount() == 0) {
				player.getPackets().sendGameMessage(
						"There is no stock of that item at the moment.");
				return;
			}
			int dq = clickSlot >= mainStock.length ? 0 : defaultQuantity[clickSlot];
			int price = getBuyPrice(item, dq);
			int amountCoins = player.getInventory().getItems().getNumberOf(money);
			int amountInPouch = player.money;
			int maxPouch = amountInPouch / price;
			int maxQuantity = amountCoins / price;
			int buyQ = item.getAmount() > quantity ? quantity : item.getAmount();

			boolean enoughCoins = maxQuantity >= buyQ;
			boolean enoughInPouch = maxPouch >= buyQ;
	        ItemDefinitions defs = item.getDefinitions();
			if (money != 995) {
				for (int i11 = 0; i11 < loyaltyPrices.length; i11++) {
					loyaltyShop = 1;
					if (item.getId() == loyaltyPrices[i11][0]) {
						if (player.getLoyaltyPoints() < loyaltyPrices[i11][1] * quantity) {
							player.getPackets().sendGameMessage("You need " + loyaltyPrices[i11][1] + " loyalty Points to buy this item!");
							return;
						} else
							loyaltyShop = 1;
						player.getPackets().sendGameMessage("You have bought a " + item.getDefinitions().getName() + " from the loyalty store.");
						player.getInventory().addItem(loyaltyPrices[i11][0], 1);
						player.setLoyaltyPoints(player.getLoyaltyPoints() - loyaltyPrices[i11][1]);
						player.getPackets().sendGameMessage("You currently have " + "<col=008000>" +player.getLoyaltyPoints()+ "</col>" + " loyalty points!");
						return;
					}
				}
				for (int i11 = 0; i11 < Voteprices.length; i11++) {
					VoteShop = 1;
					if (item.getId() == Voteprices[i11][0]) {
						if (player.getVotePoints() < Voteprices[i11][1] * quantity) {
							player.getPackets().sendGameMessage("You need " + Voteprices[i11][1] + " voting points to buy this item!");
							return;
						} else
							VoteShop = 1;
						player.getPackets().sendGameMessage("You have bought a " + item.getDefinitions().getName() + " from the voting store.");
						player.getInventory().addItem(Voteprices[i11][0], 1);
						player.setVotePoints(player.getVotePoints() - Voteprices[i11][1]);
						player.getPackets().sendGameMessage("You currently have " + "<col=FF0000>" +player.getVotePoints()+ "</col>" + " voting points!");
						return;
					}
				}
			}
			if (!enoughCoins && !enoughInPouch) {
				player.getPackets().sendGameMessage("You don't have enough coins.");
				buyQ = maxQuantity;
	        } else if (quantity > buyQ) {
	            player.getPackets().sendGameMessage("The shop has run out of stock.");
				ShopsHandler.init();
				refreshShop();
	            if (!item.getDefinitions().isStackable() && !defs.isStackable() &&player.getInventory().getFreeSlots() < 1) {
	                    player.getPackets().sendGameMessage("Not enough space in your inventory.");
	                    return;
	            }
	        } else {
	            int freeSlots = player.getInventory().getFreeSlots();
	            if (!item.getDefinitions().isNoted() && buyQ > freeSlots && !defs.isStackable()) {
	                buyQ = freeSlots;
	                player.getPackets().sendGameMessage("Not enough space in your inventory.");
	            }
	        }
			if (buyQ != 0) {
				if (amountCoins + price < 2147000001) {
					if (enoughInPouch) {
						int FirstAmount = player.getInventory().getItems().getNumberOf(item.getId());
						player.getInventory().addItem(item.getId(), buyQ);
						int SecondAmount = player.getInventory().getItems().getNumberOf(item.getId());
						int Amounts = SecondAmount - FirstAmount;
						int totalPrice = price * Amounts;
						player.getPackets().sendRunScript(5561, 0, totalPrice);
						player.money -= totalPrice;
						player.refreshMoneyPouch();
					} else {
						int FirstAmount = player.getInventory().getItems().getNumberOf(item.getId());
						player.getInventory().addItem(item.getId(), buyQ);
						int SecondAmount = player.getInventory().getItems().getNumberOf(item.getId());
						int Amounts = SecondAmount - FirstAmount;
						int totalPrice = price * Amounts;
						player.getInventory().deleteItem(money, totalPrice);
					}
					item.setAmount(item.getAmount() - buyQ);
					if (item.getAmount() <= 0 && clickSlot >= mainStock.length)
						generalStock[clickSlot - mainStock.length] = null;
					refreshShop();
					sendInventory(player);
				} else {
					player.getPackets().sendGameMessage("You can't have more then 2147M coins in your inventory.");
					return;
				}
			}
		}

		public static int loyaltyShop = 0;
		
		public static int VoteShop = 0;
		
	    public void restoreItems() {
	        boolean needRefresh = false;
	        for (int i = 0; i < mainStock.length; i++) {
	            if (mainStock[i].getAmount() < defaultQuantity[i]) {
	                mainStock[i].setAmount(mainStock[i].getAmount() + 1);
	                needRefresh = true;
	            } else if (mainStock[i].getAmount() > defaultQuantity[i]) {
	                mainStock[i].setAmount(mainStock[i].getAmount() + -1);
	                needRefresh = true;
	            }
	        }
	        if (generalStock != null) {
	            for (int i = 0; i < generalStock.length; i++) {
	                Item item = generalStock[i];
	                if (item == null)
	                    continue;
	                item.setAmount(item.getAmount() - 1);
	                if (item.getAmount() <= 0)
	                    generalStock[i] = null;
	                needRefresh = true;
	            }
	        }
	        if (needRefresh)
	            refreshShop();
	    }

		private boolean addItem(int itemId, int quantity) {
			for (Item item : mainStock) {
				if (item.getId() == itemId) {
					item.setAmount(item.getAmount() + quantity);
					refreshShop();
					return true;
				}
			}
			if (generalStock != null) {
				for (Item item : generalStock) {
					if (item == null)
						continue;
					if (item.getId() == itemId) {
						item.setAmount(item.getAmount() + quantity);
						refreshShop();
						return true;
					}
				}
				for (int i = 0; i < generalStock.length; i++) {
					if (generalStock[i] == null) {
						generalStock[i] = new Item(itemId, quantity);
						refreshShop();
						return true;
					}
				}
			}
			return false;
		}

		public void sell(Player player, int slotId, int quantity) {
			if (player.getInventory().getItemsContainerSize() < slotId)
				return;
			Item item = player.getInventory().getItem(slotId);
			if (item == null)
				return;
			int originalId = item.getId();
			if (item.getDefinitions().isNoted())
				item = new Item(item.getDefinitions().getCertId(), item.getAmount());
			if (item.getDefinitions().isDestroyItem()
					|| ItemConstants.getItemDefaultCharges(item.getId()) != -1
					|| !ItemConstants.isTradeable(item) || item.getId() == money) {
				player.getPackets().sendGameMessage("You can't sell this item.");
				return;
			}
			int dq = getDefaultQuantity(item.getId());
			if (dq == -1 && generalStock == null) {
				player.getPackets().sendGameMessage(
						"You can't sell this item to this shop.");
				return;
			}
			int price = getSellPrice(item, dq);
			int numberOff = player.getInventory().getItems().getNumberOf(originalId);
			if (quantity > numberOff)
				quantity = numberOff;
			if (!addItem(item.getId(), quantity)) {
				player.getPackets().sendGameMessage("Shop is currently full.");
				return;
			}
			if (player.money + price > 0) {
				player.getInventory().deleteItem(originalId, quantity);
				//player.getInventory().addItem(money, price * quantity);
				player.money += price * quantity;
				player.getPackets().sendRunScript(5561, 1, price * quantity);
				player.refreshMoneyPouch();
			} else {
				player.getPackets().sendGameMessage("You can't have more then 2147483647 coins in your pouch.");
				return;
			}
		}

		public void sendValue(Player player, int slotId) {
			if (player.getInventory().getItemsContainerSize() < slotId)
				return;
			Item item = player.getInventory().getItem(slotId);
			if (item == null)
				return;
			if (item.getDefinitions().isNoted())
				item = new Item(item.getDefinitions().getCertId(), item.getAmount());
			if (item.getDefinitions().isNoted() || !ItemConstants.isTradeable(item)
					|| item.getId() == money) {
				player.getPackets().sendGameMessage("You can't sell this item.");
				return;
			}
			int dq = getDefaultQuantity(item.getId());
			if (dq == -1 && generalStock == null) {
				player.getPackets().sendGameMessage(
						"You can't sell this item to this shop.");
				return;
			}
			int price = getSellPrice(item, dq);
			player.getPackets().sendGameMessage(
					item.getDefinitions().getName()
					+ ": shop will buy for: "
					+ price
					+ " "
					+ ItemDefinitions.getItemDefinitions(money).getName()
					.toLowerCase()
					+ ". Right-click the item to sell.");
		}

		public int getDefaultQuantity(int itemId) {
			for (int i = 0; i < mainStock.length; i++)
				if (mainStock[i].getId() == itemId)
					return defaultQuantity[i];
			return -1;
		}

		public void sendInfo(Player player, int slotId, boolean isBuying) {
			if (slotId >= getStoreSize())
				return;
			Item[] stock = isBuying ? mainStock : player.getInventory().getItems().getItems();
			Item item = slotId >= stock.length ? generalStock[slotId - stock.length] : stock[slotId];
			if (item == null)
				return;
			int price = getBuyPrice(item);
			for (int i = 0; i < loyaltyPrices.length; i++) {
				if (item.getId() == loyaltyPrices[i][0]) {
					player.getPackets().sendGameMessage("" + item.getDefinitions().getName() + " costs " + loyaltyPrices[i][1] + " loyalty points.");
					player.getPackets().sendConfig(2564, loyaltyPrices[i][1]);
					return;
				}
			}
			for (int i = 0; i < Voteprices.length; i++) {
				if (item.getId() == Voteprices[i][0]) {
					player.getPackets().sendGameMessage("" + item.getDefinitions().getName() + " costs " + Voteprices[i][1] + " voting points.");
					player.getPackets().sendConfig(2564, Voteprices[i][1]);
					return;
				}
			}
			if (item.getDefinitions().isDestroyItem()
					|| ItemConstants.getItemDefaultCharges(item.getId()) != -1
					|| !ItemConstants.isTradeable(item) || item.getId() == money) {
				player.getPackets().sendGameMessage("You can't sell this item.");
				return;
			}
			player.getPackets().sendGameMessage(item.getDefinitions().getName() + ": shop will " + (isBuying ? "sell" : "buy") +" for " + price + " " + ItemDefinitions.getItemDefinitions(money).getName().toLowerCase() + ".");
		}

		public int getBuyPrice(Item item) {
			int price = item.getDefinitions().getValue();
			if (price == 0)
				price = 1;
			return price;
		}

		public int getSellPrice(Item item, int dq) {
			return item.getDefinitions().getValue() / 2;
		}

		public void sendExamine(Player player, int slotId) {
			if (slotId >= getStoreSize())
				return;
			Item item = slotId >= mainStock.length ? generalStock[slotId
			                                                      - mainStock.length] : mainStock[slotId];
			if (item == null)
				return;
			player.getPackets().sendGameMessage(ItemExamines.getExamine(item));
		}

		public void refreshShop() {
			for (Player player : viewingPlayers) {
				sendStore(player);
				player.getPackets().sendIComponentSettings(620, 25, 0,
						getStoreSize() * 6, 1150);
			}
		}

		public int getStoreSize() {
			return mainStock.length
					+ (generalStock != null ? generalStock.length : 0);
		}

		public void sendStore(Player player) {
			Item[] stock = new Item[mainStock.length
			                        + (generalStock != null ? generalStock.length : 0)];
			System.arraycopy(mainStock, 0, stock, 0, mainStock.length);
			if (generalStock != null)
				System.arraycopy(generalStock, 0, stock, mainStock.length,
						generalStock.length);
			player.getPackets().sendItems(MAIN_STOCK_ITEMS_KEY, stock);
		}

		public void sendSellStore(Player player, Item[] inventory) {
			Item[] stock = new Item[inventory.length + (generalStock != null ? generalStock.length : 0)];
			System.arraycopy(inventory, 0, stock, 0, inventory.length);
			if (generalStock != null)
				System.arraycopy(generalStock, 0, stock, inventory.length, generalStock.length);
			player.getPackets().sendItems(MAIN_STOCK_ITEMS_KEY, stock);
		}
	        public int getBuyPrice(Item item, int dq) {
	              int price = item.getDefinitions().getValue();
	              if (price == 0)
	              price = 1;
	              return price;
	        }

		public void handleShop(Player player, int slotId, int amount) {
			boolean isBuying = player.getTemporaryAttributes().get("shop_buying") != null;
			if (isBuying)
				buy(player, slotId, amount);
			else
				sell(player, slotId, amount);
		}

		public Item[] getMainStock() {
			return this.mainStock;
		}
		
		public int getAmount() {
			return this.amount;
		}

		public void setAmount(Player player, int amount) {
			this.amount = amount;
			player.getPackets().sendIComponentText(1265, 67, String.valueOf(amount)); //just update it here
		}
	}